﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Data;
using System.ComponentModel;
using System.Windows;
using SilverlightDebateViewModel.SilverlightDebateWS;
using System.Windows.Input;
using System.Collections.ObjectModel;

namespace SilverlightDebateViewModel
{
    public class StatementViewModel : INotifyPropertyChanged
    {
        #region Constructor
        public StatementViewModel()
        {
            LoadSelectedStatementCommand = new DelegateCommand(LoadStatement, CanLoadStatement);
            LoadAgreeOpinionsCommand = new DelegateCommand(LoadAgreeOpinions, CanLoadAgreeOpinions);
            LoadDisagreeOpinionsCommand = new DelegateCommand(LoadDisagreeOpinions, CanLoadDisagreeOpinionsCommand);
            SetSelectedStatementCommand = new DelegateCommand(SetSelectedStatemenet, CanSetSelectedStatementCommand);
            CheckCanVoteCommand = new DelegateCommand(CheckCanVote, CanCheckCanVoteCommand);
            ResetVoteCommand = new DelegateCommand(ResetVote, CanResetVoteCommand);
            CreateNewOpinionCommand = new DelegateCommand(CreateNewOpinion, CanCreateNewOpinionCommand);
            SetNewOpinionReturnICommand = new DelegateCommand(SetNewOpinionReturn, CanSetNewOpinionReturnCommand);

            AgreedOpinionsList = new ObservableCollection<OpinionViewModel>();
            DisagreeOpinionsList = new ObservableCollection<OpinionViewModel>();
        }
        #endregion

        // Properties 

        #region VMMainPageViewModel
        private MainPageViewModel _VMMainPageViewModel;
        public MainPageViewModel VMMainPageViewModel
        {
            get { return _VMMainPageViewModel; }
            set
            {
                if (VMMainPageViewModel == value)
                {
                    return;
                }
                _VMMainPageViewModel = value;
                this.NotifyPropertyChanged("VMMainPageViewModel");
            }
        }
        #endregion

        #region SelectedStatement
        private Statement _SelectedStatement;
        public Statement SelectedStatement
        {
            get { return _SelectedStatement; }
            set
            {
                if (_SelectedStatement == value)
                {
                    return;
                }
                _SelectedStatement = value;
                this.NotifyPropertyChanged("SelectedStatement");
            }
        }
        #endregion

        #region TotalVotes
        private int _TotalVotes;
        public int TotalVotes
        {
            get { return this._TotalVotes; }
            set
            {
                if (this._TotalVotes != value)
                {
                    this._TotalVotes = value;
                    this.NotifyPropertyChanged("TotalVotes");
                }
            }
        }
        #endregion

        #region AgreeOpinionslist
        private ObservableCollection<OpinionViewModel> _AgreedOpinionsList;
        public ObservableCollection<OpinionViewModel> AgreedOpinionsList
        {
            get { return _AgreedOpinionsList; }
            set
            {
                if (this._AgreedOpinionsList != value)
                {
                    this._AgreedOpinionsList = value;
                    this.NotifyPropertyChanged("AgreedOpinionsList");
                }
            }
        }
        #endregion

        #region DisagreeOpinionslist
        private ObservableCollection<OpinionViewModel> _DisagreeOpinionsList;
        public ObservableCollection<OpinionViewModel> DisagreeOpinionsList
        {
            get { return _DisagreeOpinionsList; }
            set
            {
                if (this._DisagreeOpinionsList != value)
                {
                    this._DisagreeOpinionsList = value;
                    this.NotifyPropertyChanged("DisagreeOpinionsList");
                }
            }
        }
        #endregion

        #region SelectedOpinion
        private Opinion _SelectedOpinion;
        public Opinion SelectedOpinion
        {
            get { return this._SelectedOpinion; }
            set
            {
                if (this._SelectedOpinion != value)
                {
                    this._SelectedOpinion = value;
                    this.NotifyPropertyChanged("SelectedOpinion");
                }
            }
        }
        #endregion

        #region CanVote
        private bool _CanVote;
        public bool CanVote
        {
            get { return this._CanVote; }
            set
            {
                if (this._CanVote != value)
                {
                    this._CanVote = value;
                    this.NotifyPropertyChanged("CanVote");
                }
            }
        }
        #endregion

        // ICommands

        #region SetSelectedStatementCommand
        public ICommand SetSelectedStatementCommand { get; set; }
        private bool CanSetSelectedStatementCommand(object param)
        {
            return ((param as Statement) != null);
        }
        public void SetSelectedStatemenet(object param)
        {
            SelectedStatement = (Statement)param;
            GetStatement();
        }
        #endregion

        #region LoadSelectedStatementCommand
        public ICommand LoadSelectedStatementCommand { get; set; }
        private bool CanLoadStatement(object param)
        {
            return true;
        }
        public void LoadStatement(object param)
        {
            GetStatement();
        }
        #endregion

        #region ReloadStatementStatsCommand

        public ICommand ReloadStatementCommand { get; set; }
        private bool CanReloadStatementCommand(object param)
        {
            return SelectedStatement != null;
        }
        public void ReloadStatement(object param)
        {
            ReloadStatement();
        }
        #endregion

        #region LoadAgreeOpinionList
        public ICommand LoadAgreeOpinionsCommand { get; set; }
        private bool CanLoadAgreeOpinions(object param)
        {
            if (SelectedStatement != null)
            {
                return (SelectedStatement.StatementID != 0);
            }
            else
            {
                return false;
            }
        }
        public void LoadAgreeOpinions(object param)
        {
            string baseAddress = VMMainPageViewModel.BaseAddressProperty;
            RIAAuthenticationHeader riaHeader = VMMainPageViewModel.RIAAuthenticationHeaderProperty;

            DebateModel.GetOpinions(SelectedStatement.StatementID, true, riaHeader, baseAddress, (sender, EventArgs) =>
                {
                    if (EventArgs.Error == null)
                    {
                        AgreedOpinionsList.Clear();
                        
                        foreach (Opinion op in EventArgs.Result)
                        {
                            AgreedOpinionsList.Add(new OpinionViewModel()
                            {
                                ObjOpinion = op,
                                VMStatementViewModel = this,
                            });
                        }

                    }
                    else
                    {
                        //bugbug
                    }

                });

        }
        #endregion

        #region LoadDisagreeOpinionList
        public ICommand LoadDisagreeOpinionsCommand { get; set; }
        private bool CanLoadDisagreeOpinionsCommand(object param)
        {
            if (SelectedStatement != null)
            {
                return (SelectedStatement.StatementID != 0);
            }
            else
            {
                return false;
            }
        }
        public void LoadDisagreeOpinions(object param)
        {
            string baseAddress = VMMainPageViewModel.BaseAddressProperty;
            RIAAuthenticationHeader riaHeader = VMMainPageViewModel.RIAAuthenticationHeaderProperty;

            DebateModel.GetOpinions(SelectedStatement.StatementID, false, riaHeader, baseAddress, (sender, EventArgs) =>
            {
                if (EventArgs.Error == null)
                {
                    DisagreeOpinionsList.Clear();

                    foreach (Opinion op in EventArgs.Result as IEnumerable<Opinion>)
                    {
                        DisagreeOpinionsList.Add(new OpinionViewModel()
                        {
                            ObjOpinion = op,
                            VMStatementViewModel = this,
                        });
                    }
                }
                else
                {
                    //BUGBUG 
                }
            });
        }
        #endregion

        #region CheckCanVote
        public ICommand CheckCanVoteCommand { get; set; }
        private bool CanCheckCanVoteCommand(object param)
        {
            try
            {
                return (SelectedStatement.StatementID != 0);
            }
            catch
            {
                return false;
            }
        }
        public void CheckCanVote(object param)
        {
            string baseAddress = VMMainPageViewModel.BaseAddressProperty;
            RIAAuthenticationHeader riaHeader = VMMainPageViewModel.RIAAuthenticationHeaderProperty;

            DebateModel.CanVote(SelectedStatement.StatementID, riaHeader, baseAddress, (sender, EventArgs) =>
                {
                    if (EventArgs.Error == null)
                    {
                        CanVote = EventArgs.Result;
                    }
                    else
                    {
                        //BUGBUG ADD error handling message
                    }
                });
        }

        #endregion

        #region ResetVoteCommand
        public ICommand ResetVoteCommand { get; set; }
        private bool CanResetVoteCommand(object param)
        {
            if (SelectedStatement != null)
            {
                return (SelectedStatement.StatementID != 0);
            }
            else
            {
                return false;
            }
        }
        public void ResetVote(object param)
        {
            string baseAddress = VMMainPageViewModel.BaseAddressProperty;
            RIAAuthenticationHeader riaHeader = VMMainPageViewModel.RIAAuthenticationHeaderProperty;

            DebateModel.ResetVote(SelectedStatement.StatementID, riaHeader, baseAddress, (sender, EventArgs) =>
            {
                if (EventArgs.Error == null & EventArgs.Result)
                {
                    CanVote = true;

                    ReloadStatement();
                }
                else
                {
                    //BUGBUG ADD error handling message
                }
            });
        }
        #endregion

        #region CreateNewOpinionCommand
        public ICommand CreateNewOpinionCommand { get; set; }
        private bool CanCreateNewOpinionCommand(object param)
        {
            if (SelectedStatement != null)
            {
                return (SelectedStatement.StatementID != 0);
            }
            else
            {
                return false;
            }
        }
        public void CreateNewOpinion(object param)
        {
            string baseAddress = VMMainPageViewModel.BaseAddressProperty;
            RIAAuthenticationHeader riaHeader = VMMainPageViewModel.RIAAuthenticationHeaderProperty;
            
            Opinion op = param as Opinion;

            if(op != null)
            {
                DebateModel.CreateNewOpinion(SelectedStatement.StatementID, op._Agree, op._Title, riaHeader, baseAddress, (sender, EventArgs) =>
                    {

                        if (EventArgs.Error == null)
                        {
                            CanVote = false;

                            ReloadStatement();
                            //if (op._Agree)
                            //{
                            //    LoadAgreeOpinions(null);
                            //}
                            //else
                            //{
                            //    LoadDisagreeOpinions(null);
                            //}
                        }
                        else
                        {
                            op.Errors.Add(EventArgs.Error.ToString());
                        }
                    });

            }

        }

        #endregion

        #region SetNewOpinionReturnICommand
        public ICommand SetNewOpinionReturnICommand { get; set; }
        public void SetNewOpinionReturn(object param)
        {
            VMMainPageViewModel.ReturnICommandNewOpinion = CreateNewOpinionCommand;
        }

        private bool CanSetNewOpinionReturnCommand(object param)
        {
            return CreateNewOpinionCommand as ICommand != null; 
        }
        #endregion

        // Operations

        #region GetStatement
        private void GetStatement()
        {
            string baseAddress = VMMainPageViewModel.BaseAddressProperty;
            RIAAuthenticationHeader riaHeader = VMMainPageViewModel.RIAAuthenticationHeaderProperty;

            DebateModel.GetStatement(SelectedStatement.StatementID, riaHeader, baseAddress, (sender, EventArgs) =>
            {
                if (EventArgs.Error == null && EventArgs.Result.Errors.Count < 1)
                {
                    SelectedStatement = EventArgs.Result;
                    TotalVotes = SelectedStatement.AgreeCount + SelectedStatement.DisagreeCount;
                }
            });
        }
        #endregion

        #region ReloadStatement
        private void ReloadStatement()
        {
            string baseAddress = VMMainPageViewModel.BaseAddressProperty;
            RIAAuthenticationHeader riaHeader = VMMainPageViewModel.RIAAuthenticationHeaderProperty;

            DebateModel.GetStatement(SelectedStatement.StatementID, riaHeader, baseAddress, (sender, EventArgs) =>
            {
                if (EventArgs.Error == null && EventArgs.Result.Errors.Count < 1)
                {
                    TotalVotes = SelectedStatement.AgreeCount + SelectedStatement.DisagreeCount;

                    SelectedStatement = EventArgs.Result;

                    LoadAgreeOpinions(null);
                    LoadDisagreeOpinions(null);
                }
            });
        }


        #endregion

        // Utility

        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
        #endregion

    }
}